﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;

namespace VRP_Saving_Final
{
    //this reads the input file
    class input
    {
        public static void readingdatafile( VRP inputdata, string inputfile) //string inputfile is the name for the input file
        {
            //This function will read the input file line by line
            int counter = 0;
            string line;                               // string variable for each line.
            double[,] ODmatrix = new double[10000, 2]; // we assume there will not be over 10000 nodes. 
            float[] Demand = new float[10000];         
            System.IO.StreamReader file =
                new System.IO.StreamReader(inputfile); // read the input file
            bool COOR_SEC = false;                     // COOR_SEC will be true once we are in the coordinate section
            bool DEMAND_SEC = false;                   // DEMAND_SEC will be true once we are in the demand section
            while ((line = file.ReadLine()) != null)
            {
                if (line.IndexOf("EOF") != -1)//       // stop reading when we reach EOF
                {
                    break;

                }

                if (line.IndexOf("NAME") != -1)        // read the file's name
                {
                    System.Console.WriteLine(line);
                }
                if (line.IndexOf("COMMNET") != -1)     // ignore it now
                {
                    //don't need to consider right now
                }

                if (line.IndexOf("BEST_KNOWN") != -1)  // reading the optimal solution 
                {
                    string[] w = Regex.Split(line, @"\W+");
                    inputdata.optimal_solution = float.Parse(w[1]);  // convert the string varible to float variable

                }


                if (line.IndexOf("MAX. LENGTH") != -1)  // reading the optimal solution 
                {

                    string[] w = Regex.Split(line, @"\W+");
                    inputdata.maxLength = double.Parse(w[2]);  // yyyeeeeeeeah. Actually this reads in the max length.

                }

                if (line.IndexOf("TYPE") != -1 && line.IndexOf("EDGE_WEIGHT_TYPE") == -1)// reading the tpe of the input file
                {
                    string[] w = Regex.Split(line, @"\W+");
                    if (w[1] != "CVRP" && w[1] != "DCVRP")
                    {
                        Console.WriteLine("ERROR!TYPE SHOULD BE CVRP or DCVRP");                  // it should always be CVRP in our case
                        Console.WriteLine(w[1]);
                        inputdata.error = true;                                          // if not, return the error, stop the program
                        return;
                    }
                }

                if (line.IndexOf("DIMENSION") != -1)                                     // reading number of nodes in the input file
                {
                    string[] w = Regex.Split(line, @"\W+");                              
                    inputdata.numnodes = int.Parse(w[1]);

                }
                if (line.IndexOf("EDGE_WEIGHT_TYPE") != -1)                              // read the edge type
                {
                    string[] w = Regex.Split(line, @"\W+");
                    if (w[1] != "EUC_2D" && w[1] != "EXACT_2D")
                    {
                        Console.WriteLine("ERROR! EDGE WIGHT TYPE SHOULD BE EUC_2D OR EXACT_2D");
                        inputdata.error = true;
                        return;                                                           // it should be only EUC_2D or EXACT_2D, otherwise, return error
                    }
                }
                if (line.IndexOf("CAPACITY") != -1)                                       // read the capacity               
                {   
                    string[] w = Regex.Split(line, @"\W+");                               
                    inputdata.capacity = int.Parse(w[1]);
                }

                if (line.IndexOf("NODE_COORD_SECTION") != -1)                             // begin to read coordinate section
                {
                    COOR_SEC = true;     // begin read the coordinate 
                    DEMAND_SEC = false;
                    continue;
                }

                if (line.IndexOf("EDGE_WEIGHT_FORMAT") != -1)                             // read the edge weight format, it should always be FUNCTION
                {
                    string[] w = Regex.Split(line, @"\W+");
                    if (w[1] != "FUNCTION")
                    {
                        Console.WriteLine("ERROR!SHOULD ALWAYS BE FUNCTION!!");
                        inputdata.error = true;
                    }
                }
                if (line.IndexOf("DEMAND_SECTION") != -1)                                 // begin to read the demand section
                {
                    COOR_SEC = false;
                    DEMAND_SEC = true;
                    counter = 0;
                    continue;
                }



                if (line.IndexOf("DEPOT_SECTION") != -1)//                                 // read the depot section 
                {
                    COOR_SEC = false;
                    DEMAND_SEC = false;
                }

                if (COOR_SEC)   // begin reading the coordinate section
                {
                    string[] words = line.Split(' ');
                    int len = words.Count();
                    if (len > 3)                                                           // if there is extra space in front of the line
                    {
                        ODmatrix[counter, 0] = double.Parse(words[len-2]);                 // counter.x
                        ODmatrix[counter, 1] = double.Parse(words[len-1]);                 // counter.y
                        counter++;
                    }
                    else                    
                    {
                        ODmatrix[counter, 0] = double.Parse(words[1]);                      //counter.x          
                        ODmatrix[counter, 1] = double.Parse(words[2]);                      //counter.y
                        counter++;
                    }

                }
                if (DEMAND_SEC)  // begin readin the demand section
                {
                    string[] w = Regex.Split(line, @"\W+");
                    Demand[counter] = float.Parse(w[1]);                                    //read capacity to the demand array
                    if (counter == 0)
                    {
                        if (Demand[0] != 0)                                                 //the demand at depot should always be 0, otherwise return error.
                        {
                            Console.WriteLine("ERROR!DEMAND AT DEPOT SHOULD BE 0!");
                            inputdata.error = true;
                            return;
                        }
                    }

                    counter++;
                }

            }

            
            inputdata.demandarray = new float[inputdata.numnodes];                          // initialize the demandarray
            inputdata.costmatrix = new float[inputdata.numnodes, inputdata.numnodes];       // initialize the costmatrix 

            for (int i = 0; i < inputdata.numnodes; i++)                                    // changing the demand array
            {
                inputdata.demandarray[i] = Demand[i];
            }

            for (int i = 0; i < inputdata.numnodes; i++)                                     //calculate the ODmatrix
            {
                for (int j = 0; j < inputdata.numnodes; j++)
                {

                    inputdata.costmatrix[i, j] = (float) Math.Sqrt(Math.Pow((ODmatrix[i, 0] - ODmatrix[j, 0]), 2) + Math.Pow((ODmatrix[i, 1] - ODmatrix[j, 1]), 2));
                    if (i == j)
                    {
                        inputdata.costmatrix[i, j] = 1000000;                                //
                    } 
                }
            }

            file.Close();
        }
    }
}
